// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.designer.ui.process.editors;

import java.util.ArrayList;
import java.util.List;

import org.dengues.core.CorePlugin;
import org.dengues.core.IDesignerCoreService;
import org.dengues.core.IWarehousePluginService;
import org.dengues.core.components.ENodeParameterName;
import org.dengues.core.components.NodePropertyParameter;
import org.dengues.core.editor.AbstractEditorInput;
import org.dengues.core.metadata.MetadataColumn;
import org.dengues.core.metadata.MetadataTable;
import org.dengues.core.process.EConnectionType;
import org.dengues.core.process.ICompConnection;
import org.dengues.core.resource.WarehouseResourceFactory;
import org.dengues.core.runprocess.IJavaETLProcessor;
import org.dengues.core.warehouse.ENodeCategoryName;
import org.dengues.core.warehouse.IWarehouseNode;
import org.dengues.designer.ui.process.models.CompBlock;
import org.dengues.designer.ui.process.models.CompConnection;
import org.dengues.designer.ui.process.models.CompNode;
import org.dengues.designer.ui.process.models.CompNote;
import org.dengues.designer.ui.process.models.CompProcess;
import org.dengues.model.warehouse.BlockType;
import org.dengues.model.warehouse.ColumnType;
import org.dengues.model.warehouse.ConnectionType;
import org.dengues.model.warehouse.ElementParameterType;
import org.dengues.model.warehouse.MetadataType;
import org.dengues.model.warehouse.NodeType;
import org.dengues.model.warehouse.NoteType;
import org.dengues.model.warehouse.ProcessType;
import org.dengues.model.warehouse.WarehouseFactory;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.common.util.EList;

/**
 * qzhang class global comment. Detailled comment <br/>
 */
public class ProcessEditorInput extends AbstractEditorInput {

    private CompProcess process;

    private final ProcessType processType;

    /**
     * qzhang ProcessEditorInput constructor comment.
     * 
     * @param processType
     */
    public ProcessEditorInput(ProcessType processType, IPath path) {
        super(processType.getName(), ENodeCategoryName.PROCESS, path);
        this.processType = processType;
    }

    /**
     * Getter for processType.
     * 
     * @return the processType
     */
    public ProcessType getProcessType() {
        return this.processType;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.part.FileEditorInput#getName()
     */
    @Override
    public String getName() {
        return processType.getName();
    }

    /**
     * Sets the warehouseNode.
     * 
     * @param warehouseNode the warehouseNode to set
     */
    public void setWarehouseNode(IWarehouseNode warehouseNode) {
        if (warehouseNode != null) {
            this.warehouseNode = warehouseNode;
        } else {
            IWarehousePluginService warehouseService = CorePlugin.getDefault().getWarehousePluginService();
            this.warehouseNode = warehouseService.getWarehouseViewFactory().createWarehouseNodeFromEMF(ENodeCategoryName.PROCESS,
                    parentNode, processType);
        }
    }

    private CompProcess loadProcess() {
        CompProcess process = new CompProcess();
        process.setName(getProcessType().getName());
        List<NodeType> nodes = getProcessType().getNode();
        for (NodeType type : nodes) {
            CompNode compNode = new CompNode(getComponent(type.getCompName()));
            compNode.setLocation(new Point(type.getPosX(), type.getPosY()));
            List<ElementParameterType> elementParameters = type.getElementParameter();
            for (ElementParameterType elementParamType : elementParameters) {
                compNode.getElementParameter(elementParamType.getName()).setValue(elementParamType.getValue());
            }
            compNode.getNodeLabel().setNodeLabel(
                    compNode.getElementParameter(ENodeParameterName.UNIQUE_NAME.getName()).getValue().toString());
            compNode.setCompProcess(process);
            process.addCompNode(compNode);
            process.addCompNodeLabel(compNode.getNodeLabel());
            process.addCompNodeStatus(compNode.getNodeStatus());
            EList metadata = type.getMetadata();
            if (metadata.size() > 0) {
                MetadataType metadataType = (MetadataType) metadata.get(0);
                MetadataTable table = new MetadataTable();
                table.setTableName(metadataType.getName());
                List<ColumnType> cs = metadataType.getColumn();
                List<MetadataColumn> cols = new ArrayList<MetadataColumn>();
                for (ColumnType columnType : cs) {
                    MetadataColumn column = new MetadataColumn();
                    column.setColumnName(columnType.getName());
                    column.setType(columnType.getType());
                    cols.add(column);
                }
                table.setColumns(cols);
                compNode.getMetadataList().add(table);
            }
        }
        List<NoteType> notes = getProcessType().getNote();
        for (NoteType type : notes) {
            CompNote compNote = new CompNote();
            compNote.setOpaque(type.isOpaque());
            compNote.setLocation(new Point(type.getPosX(), type.getPosY()));
            compNote.setSize(new Dimension(type.getSizeW(), type.getSizeH()));
            compNote.setText(type.getText());
            process.addCompNote(compNote);
            compNote.setCompProcess(process);
        }
        List<BlockType> blocks = getProcessType().getBlock();
        for (BlockType type : blocks) {
            CompBlock compNote = new CompBlock();
            compNote.setLocation(new Point(type.getPosX(), type.getPosY()));
            compNote.setSize(new Dimension(type.getSizeW(), type.getSizeH()));
            compNote.setName(type.getName());
            compNote.setColor(type.getColor());
            process.addCompBlock(compNote);
            compNote.setCompProcess(process);
        }
        List<ConnectionType> connections = getProcessType().getConnection();
        for (ConnectionType connType : connections) {
            String source = connType.getSource();
            CompNode sourceNode = getCompNode(process, source);
            CompNode targetNode = getCompNode(process, connType.getTarget());
            if (sourceNode != null && targetNode != null) {
                CompConnection compConnection = new CompConnection(sourceNode, targetNode, EConnectionType.MAIN, connType
                        .getName());
                process.addCompConnectionLabel(compConnection.getConnectionLabel());
                process.addCompConnectionTrac(compConnection.getConnectionTrac());
            }
        }
        return process;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getCompNode".
     * 
     * @param process
     * @param unName
     * @return
     */
    private CompNode getCompNode(CompProcess process, String unName) {
        for (CompNode node : process.getCompNodes()) {
            if (node.getUniqueName().equals(unName)) {
                return node;
            }
        }
        return null;
    }

    /**
     * Getter for process.
     * 
     * @return the process
     */
    public CompProcess getProcess() {
        if (process == null) {
            process = loadProcess();
        }
        return this.process;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "saveEMF".
     * 
     * @param process
     */
    public void saveEMF(CompProcess process) {
        List<CompNode> compNodes = process.getCompNodes();
        getProcessType().getNode().clear();
        getProcessType().getConnection().clear();
        for (CompNode node : compNodes) {
            NodeType nodeType = WarehouseFactory.eINSTANCE.createNodeType();
            nodeType.setCompName(node.getComponent().getName());
            nodeType.setPosX(node.getLocation().x);
            nodeType.setPosY(node.getLocation().y);
            saveElementParameters(nodeType, node);
            saveConnections(node);
            saveMetadata(nodeType, node);
            getProcessType().getNode().add(nodeType);
        }

        List<CompNote> compNotes = process.getCompNotes();
        getProcessType().getNote().clear();
        for (CompNote node : compNotes) {
            NoteType nodeType = WarehouseFactory.eINSTANCE.createNoteType();
            nodeType.setPosX(node.getLocation().x);
            nodeType.setPosY(node.getLocation().y);
            nodeType.setOpaque(node.isOpaque());
            nodeType.setText(node.getText());
            nodeType.setSizeH(node.getSize().height);
            nodeType.setSizeW(node.getSize().width);
            getProcessType().getNote().add(nodeType);
        }

        List<CompBlock> compBlocks = process.getCompBlocks();
        getProcessType().getBlock().clear();
        for (CompBlock node : compBlocks) {
            BlockType nodeType = WarehouseFactory.eINSTANCE.createBlockType();
            nodeType.setPosX(node.getLocation().x);
            nodeType.setPosY(node.getLocation().y);
            nodeType.setSizeH(node.getSize().height);
            nodeType.setSizeW(node.getSize().width);
            nodeType.setColor(node.getColor());
            nodeType.setName(node.getName());
            getProcessType().getBlock().add(nodeType);
        }

        WarehouseResourceFactory.save(getProcessType());
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "saveMetadata".
     * 
     * @param nodeType
     * 
     * @param node
     */
    private void saveMetadata(NodeType nodeType, CompNode node) {
        List<MetadataTable> metadata = node.getMetadataList();
        for (MetadataTable metadataTable : metadata) {
            MetadataType metadataType = WarehouseFactory.eINSTANCE.createMetadataType();
            metadataType.setName(metadataTable.getTableName());
            List<MetadataColumn> columns = metadataTable.getColumns();
            for (MetadataColumn metadataColumn : columns) {
                ColumnType columnType = WarehouseFactory.eINSTANCE.createColumnType();
                columnType.setName(metadataColumn.getColumnName());
                columnType.setType(metadataColumn.getType());
                metadataType.getColumn().add(columnType);
            }
            nodeType.getMetadata().add(metadataType);
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "saveConnections".
     * 
     * @param nodeType
     * @param node
     */
    private void saveConnections(CompNode node) {
        List<ICompConnection> ins = node.getIncomingConnections();
        for (ICompConnection conn : ins) {
            ConnectionType connType = WarehouseFactory.eINSTANCE.createConnectionType();
            connType.setSource(conn.getSource().getUniqueName());
            connType.setTarget(node.getUniqueName());
            connType.setName(conn.getName());
            getProcessType().getConnection().add(connType);
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "saveElementParameters".
     * 
     * @param nodeType
     * @param node
     */
    private void saveElementParameters(NodeType nodeType, CompNode node) {
        List<NodePropertyParameter> elementParameters = node.getElementParameters();
        nodeType.getElementParameter().clear();
        for (NodePropertyParameter nodePropertyParameter : elementParameters) {
            ElementParameterType parameterType = WarehouseFactory.eINSTANCE.createElementParameterType();
            parameterType.setField(nodePropertyParameter.getField());
            parameterType.setName(nodePropertyParameter.getName());
            Object value = nodePropertyParameter.getValue();
            parameterType.setValue(value == null ? "" : value.toString()); //$NON-NLS-1$
            nodeType.getElementParameter().add(parameterType);
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getCodeFile".
     * 
     * @return
     */
    public IFile getCodeFile() {
        IDesignerCoreService service = CorePlugin.getDefault().getDesignerCoreService();
        IJavaETLProcessor javaProcessor = service.getJavaProcessor(getProcess(), getPath());
        return javaProcessor.getCodeFile();
    }

}
